package edu.tamu.cse.teamproject1.Database;

import java.util.Date;

import edu.tamu.cse.teamproject1.Database.Interfaces.ITupleElement;

/**
 * This is a superclass to allow different tuple types
 *
 * @author Benjamin Unsworth
 * @since Release 0.1.0
 */
public class TupleElement implements ITupleElement {
	protected Object tupleValue;
	protected int size;
	protected String colName;
	protected EnumColumnType tupleType;
	boolean nullable;
	boolean key;
	boolean valueNull;
	
	/**
	 * Interface method getValue returns the object tupleValue
	 */
	@Override
	public Object getValue() {
		return tupleValue;
	}

	
	/**
	 * Set the value of this tupleElement
	 * @param value
	 */
	@Override
	public void setValue(Object value) {
		tupleValue = value;
		// Reset the value null if the value passed in is not null
		if (value != null) {
			this.valueNull = false;
		}
	}

	/**
	 * Creates a tuple element based off of its type provided
	 * @param value
	 * @param columnName
	 * @return a new tupleElement created according the the parameters
	 */
	@Override
	public ITupleElement createTupleElement(Object value, String columnName) {
		// size, nullable, and type should already be set when using the constructor
		ITupleElement newElem = null;
		if (value instanceof Integer) {
			newElem = new TupleIntegerElement((Integer) value);
		} else if (value instanceof String) {
			newElem = new TupleVarCharElement((String) value);
		} else if (value instanceof varchar){
			newElem = new TupleVarCharElement((varchar) value);
		} else if (value instanceof Float){
			newElem = new TupleFloatElement((Float) value);
		} else if (value instanceof Date){
			newElem = new TupleDateElement((Date) value);
		} else {
			throw new IllegalArgumentException("Invalid Object");
		}
		newElem.setColumnName(columnName);
		return newElem;
	}

	/**
	 * Gets the name of the column name the tuple element corresponds to 
	 * @return colName
	 */
	@Override
	public String getColumnName() {
		return colName;
	}

	/**
	 * Gets the size of the column that the tuple element corresponds to
	 * @return size
	 */
	@Override
	public int getColumnSize() {
		return size;
	}

	/**
	 * Returns the EnumColumn type of the tuple element
	 * @return tupleType
	 */
	@Override
	public EnumColumnType getColumnType() {
		return tupleType;
	}

	
	/**
	 * Determines whether the tupleElement can be null
	 * @return nullable
	 */
	@Override
	public boolean isNullable() {
		return nullable;
	}

	
	/**
	 * Set the columnName corresponding to the TupleElement
	 * @param columName
	 */
	@Override
	public void setColumnName(String columnName) {
		colName = columnName;
	}

	
	/**
	 * Set the size of the tupleElement
	 * @param columnSize
	 */
	@Override
	public void setColumnSize(int columnSize) {
		if(tupleType != EnumColumnType.varchar){
			return; //don't change the size only varchar needs to of variable size
		}else{
			size = columnSize;
		}
	}

	
	/**
	 * Set the type of the TupleElement
	 * @param columnType
	 */
	@Override
	public void setColumnType(EnumColumnType columnType) {
		if(columnType == tupleType) return; //no change needed
		tupleValue = null; //the tupleValue is now invalid
		tupleType = columnType;
	}

	
	/**
	 * Set whether the TupleElement should be nullable
	 * @param nullable
	 */
	@Override
	public void setNullable(boolean nullable) {
		this.nullable = nullable;
	}

	
	/**
	 * @return whether the TupleElement is a key
	 */
	@Override
	public boolean isKey() {
		return key;
	}

	
	/**
	 * Return whether the TupleElement is a key
	 * @param keyIs
	 */
	@Override
	public void setAsKey(boolean keyIs) {
		key = keyIs;
	}
	
	/**
	 * Tries to clone this object
	 * @return A copy of the object
	 */
	@Override
	public Object clone() {
		try {
			return super.clone();
		} catch(CloneNotSupportedException e) {
			return null;
		}
	}

	
	/**
	 * Creates and Empty Tuple Element
	 */
	@Override
	public ITupleElement createEmptyTupleElement() {
		return null;
	}

	/**
	 * Returns whether the value is null or not
	 */
	@Override
	public boolean isValueNull() {
		return this.valueNull;
	}

	/**
	 * Sets whether this tuple element should be considered to have a null
	 * value. 
	 */
	@Override
	public void setValueNull(boolean isValueNull) {
		this.valueNull = isValueNull;
	}
}
